<?php declare(strict_types=1);

namespace Distributed\Server;

use Swoft\Config\Config;
use Swoole\Server;
use Distributed\App;
use Communication\TxSocketData;
use Swoole\Process;
use Swoole\Server\Task;
use Distributed\Pool\RedisPool;


abstract class AbstractServer
{
	/**
	 * 数据库配置
	 * @var array
	 */
	protected $config = [
			'host' => '127.0.0.1',
			'port' => 9506
	];
	
	protected $setting = [
			'worker_num' => 4,
			'daemonize' => 0,
			'log_file' => '/tmp/server_logfile.txt',
			'task_enable_coroutine' => true
	];
	
	
	/**
	 * The server unique name
	 *
	 * @var string
	 */
	protected $pidName = 'wq';
	
	/**
	 * Pid file
	 *
	 * @var string
	 */
	protected $pidFile = '@runtime/wq.pid';
	
	/**
	 * Script file
	 *
	 * @var string
	 */
	protected $scriptFile = '';
	/**
	 * Record started server PIDs and with current workerId
	 *
	 * @var array
	 */
	private $pidMap = [
			'masterPid'  => 0,
			'managerPid' => 0,
			// if = 0, current is at master/manager process.
			'workerPid'  => 0,
			// if < 0, current is at master/manager process.
			'workerId'   => -1,
	];
	
	protected const END_STRING = "\r\n\r\n";
	
	
	public function __construct(array $config = [])
	{
		$this->config = array_merge($config, $this->config);
	}
	
	
	/**
	 * 连接
	 */
	public function onShutdown(Server $server)
	{
		$dbPool = App::$dbPool->getPoolList();
		/**
		 *
		 * @var \PDO $pdo
		 */
		$pdo = null;
		
		foreach ($dbPool as &$pdo) {
			$pdo = null;
		}
		

	}
	
	/**
	 * 启动
	 */
	public function onStart(Server $server)
	{
	
		// Save PID to property
		$this->setPidMap($server);
		
		$masterPid  = $server->master_pid;
		$managerPid = $server->manager_pid;
		
		$pidStr = sprintf('%s,%s', $masterPid, $managerPid);
		$title  = sprintf('%s master process (%s)', $this->pidName, $this->scriptFile);
		
		
		
		// Save PID to file
		// Set process title
		swoole_set_process_name($title);
	}
	
	/**
	 * 接收
	 */
	public function onReceive(Server $server, int $fd, int $reactor_id, string $data):void
	{
		
	}
	
	/**
	 * 关闭
	 */
	public function onClose(Server $server)
	{
		
	}
	
	public function onTask(Server $serv, Task $task): void
	{
			
	}
	/**
	 * Worker start event
	 *
	 * @param CoServer $server
	 * @param int      $workerId
	 *
	 * @throws Throwable
	 */
	public function onWorkerStart(Server $server, int $workerId): void
	{
		// Save PID and workerId
		$this->pidMap['workerId']  = $workerId;
		$this->pidMap['workerPid'] = $server->worker_pid;
		
		App::$redisPool = new RedisPool();
		
		
// 		// 连接 rabbitmq 服务
// 		$connection = new AMQPConnection([
// 				'host' => '127.0.0.1',
// 				'vhost' => '/',
// 				'port' => 5672,
// 				'login' => 'guest',
// 				'password' => 'guest'
// 		]);
		
// 		$connection->connect();
		
// 		App::$rabbitMQ = $connection;	
	}
	
	/**
	 * Manager start event
	 *
	 * @param CoServer $server
	 *
	 * @throws Throwable
	 */
	public function onManagerStart(Server $server): void
	{
		// Server pid map
		$this->setPidMap($server);
		
		// Set process title
		swoole_set_process_name(sprintf('%s manager process', $this->pidName));
		
		
	}
	
	
	/**
	 * Set pid map
	 *
	 * @param CoServer $server
	 */
	protected function setPidMap(Server $server): void
	{
		if ($server->master_pid > 0) {
			$this->pidMap['masterPid'] = $server->master_pid;
		}
		
		if ($server->manager_pid > 0) {
			$this->pidMap['managerPid'] = $server->manager_pid;
		}
	}
	
	/**
	 * 
	 * @param Server $server
	 */
	public function onManagerStop(Server $server): void
	{
		
	}
	/**
	 *
	 * @param unknown $fd
	 * @param TxSocketData $socketData
	 * @return boolean|unknown
	 */
	protected function sendMsg(int $fd, TxSocketData $socketData){
		
		$socketData->checkValid();
		$strMsg = serialize($socketData) .static::END_STRING;
		return App::$server->send($fd, $strMsg);
	}
}